package com.icesoft.core.dao.listener;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreRemove;
import javax.persistence.PreUpdate;

import com.icesoft.core.dao.suppose.BaseModelListener;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.stereotype.Component;

import com.icesoft.core.dao.base.BaseModel;

import lombok.extern.slf4j.Slf4j;

@SuppressWarnings("rawtypes")
@Slf4j
@Configuration
@EnableJpaAuditing
@Component
public class ModelListener implements BeanPostProcessor {
	private static final Map<Class<?>, Set<BaseModelListener>> modelMapHandlers = new HashMap<>();

	private static void addModelHandler(BaseModelListener<?> modelHandler) {
		Set<BaseModelListener> modelHandlers = modelMapHandlers.putIfAbsent(modelHandler.getRawClass(),
				new HashSet<>());
		if (modelHandlers == null) {
			modelHandlers = modelMapHandlers.get(modelHandler.getRawClass());
		}
		log.info("给实体{}添加监听器：{}", modelHandler.getRawClass().getSimpleName(), modelHandler.getClass());
		modelHandlers.add(modelHandler);
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean instanceof BaseModelListener) {
			addModelHandler((BaseModelListener<?>) bean);
		}
		return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
	}

	@SuppressWarnings("unchecked")
	@PrePersist
	public void prePersist(BaseModel model) {
		Set<BaseModelListener> modelHandlers = modelMapHandlers.get(model.getClass());
		if (modelHandlers == null) {
			return;
		}
		modelHandlers.forEach(modelHandler -> {
			modelHandler.prePersist(model);
		});
	}

	@PostPersist
	@SuppressWarnings("unchecked")
	public void postPersist(BaseModel model) {
		Set<BaseModelListener> modelHandlers = modelMapHandlers.get(model.getClass());
		if (modelHandlers == null) {
			return;
		}
		modelHandlers.forEach(modelHandler -> {
			modelHandler.postPersist(model);
		});
	}

	@PreRemove
	@SuppressWarnings("unchecked")
	public void preRemove(BaseModel model) {
		Set<BaseModelListener> modelHandlers = modelMapHandlers.get(model.getClass());
		if (modelHandlers == null) {
			return;
		}
		modelHandlers.forEach(modelHandler -> {
			modelHandler.preRemove(model);
		});
	}

	@PostRemove
	@SuppressWarnings("unchecked")
	public void postRemove(BaseModel model) {
		Set<BaseModelListener> modelHandlers = modelMapHandlers.get(model.getClass());
		if (modelHandlers == null) {
			return;
		}
		modelHandlers.forEach(modelHandler -> {
			modelHandler.postRemove(model);
		});
	}

	@PreUpdate
	@SuppressWarnings("unchecked")
	public void preUpdate(BaseModel model) {
		Set<BaseModelListener> modelHandlers = modelMapHandlers.get(model.getClass());
		if (modelHandlers == null) {
			return;
		}
		modelHandlers.forEach(modelHandler -> {
			modelHandler.preUpdate(model);
		});
	}

	@PostUpdate
	@SuppressWarnings("unchecked")
	public void postUpdate(BaseModel model) {
		Set<BaseModelListener> modelHandlers = modelMapHandlers.get(model.getClass());
		if (modelHandlers == null) {
			return;
		}
		modelHandlers.forEach(modelHandler -> {
			modelHandler.postUpdate(model);
		});
	}
}